package service

import (
	"errors"
	"fmt"
	"voice_chat_room/internal/config"
	"voice_chat_room/internal/model"
	"voice_chat_room/pkg/jwt"
	"voice_chat_room/pkg/passwd"
	"voice_chat_room/pkg/response"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type RegisterReq struct {
	Name            string `json:"Name" binding:"required,min=2,max=20"`
	Email           string `json:"email" binding:"required,email"`
	Password        string `json:"password" binding:"required,min=6,max=20"`
	ConfirmPassword string `json:"confirmPassword" binding:"required,min=6,max=20"`
}

func (s *RegisterReq) Register(c *gin.Context) response.Response {
	if s.Password != s.ConfirmPassword {
		return response.Error(400, "两次输入密码不一致", nil)
	}

	// 使用事务
	err := config.DB.Transaction(func(tx *gorm.DB) error {
		// 检查用户名是否已存在
		var existing model.User
		if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
			Where("name = ? OR email = ?", s.Name, s.Email).
			First(&existing).Error; err == nil {
			if existing.Name == s.Name {
				return fmt.Errorf("用户名已存在")
			}
			if existing.Email == s.Email {
				return fmt.Errorf("邮箱已存在")
			}
		} else if !errors.Is(err, gorm.ErrRecordNotFound) {
			return fmt.Errorf("数据库查询失败: %w", err)
		}
		// 密码加密
		encryptedPassword, err := passwd.EncryptPassword(s.Password)
		if err != nil {
			return fmt.Errorf("密码加密失败: %w", err)
		}
		// 创建新用户
		newUser := model.User{
			Name:     s.Name,
			Email:    s.Email,
			Password: encryptedPassword,
		}
		if err = tx.Create(&newUser).Error; err != nil {
			return fmt.Errorf("创建用户失败: %w", err)
		}

		token, err := jwt.GenerateToken(newUser.Name, newUser.ID)
		if err != nil {
			return fmt.Errorf("生成token失败: %w", err)
		}

		c.Set("token", token)

		return nil
	})
	if err != nil {
		switch err.Error() {
		case "用户名已存在", "邮箱已存在":
			return response.Error(400, err.Error(), nil)
		default:
			return response.Error(500, "注册失败", err)
		}
	}
	token, _ := c.Get("token")
	return response.Success(gin.H{"token": token})
}

type LoginReq struct {
	Name     string `json:"name" binding:"required,min=2,max=20"`
	Password string `json:"password" binding:"required,min=6,max=20"`
}

func (s *LoginReq) Login(c *gin.Context) response.Response {
	// 检查用户名是否存在
	var user model.User
	if err := config.DB.Where("name = ?", s.Name).First(&user).Error; err != nil {
		return response.Error(400, "用户名不存在", nil)
	}
	// 校验密码
	if !passwd.CheckPasswordHash(s.Password, user.Password) {
		return response.Error(400, "密码错误", nil)
	}
	// 生成token
	token, err := jwt.GenerateToken(user.Name, user.ID)
	if err != nil {
		return response.Error(500, "生成token失败", err)
	}
	return response.Success(gin.H{"token": token})
}

// 修改密码
type ChangePasswordReq struct {
	OldPassword     string `json:"oldPassword" binding:"required,min=6,max=20"`
	NewPassword     string `json:"newPassword" binding:"required,min=6,max=20"`
	ConfirmPassword string `json:"confirmPassword" binding:"required,min=6,max=20"`
}

func (s *ChangePasswordReq) ChangePassword(c *gin.Context) response.Response {
	if s.NewPassword != s.ConfirmPassword {
		return response.Error(400, "两次输入密码不一致", nil)
	}
	user, _ := c.Get("user")

	var oldUser model.User
	err := config.DB.Where("id = ?", user.(model.User).ID).
		Where("name = ?", user.(model.User).Name).
		First(&oldUser).Error
	if err != nil {
		return response.Error(400, "用户不存在", nil)
	}
	// 校验旧密码
	if !passwd.CheckPasswordHash(s.OldPassword, oldUser.Password) {
		return response.Error(400, "旧密码错误", nil)
	}
	// 密码加密
	encryptedPassword, err := passwd.EncryptPassword(s.NewPassword)
	if err != nil {
		return response.Error(500, "密码加密失败", err)
	}
	// 更新密码
	if err := config.DB.Model(&model.User{}).Where("id = ?", c.GetInt("userID")).
		Update("password", encryptedPassword).Error; err != nil {
		return response.Error(500, "更新密码失败", err)
	}
	return response.Success(gin.H{"message": "密码修改成功"})
}
